<template>
	<view class="content">

		<view style="width: 100%;height: 100%;position: fixed;z-index: 2;">
			
		</view>

		<view v-if="typemode == 'start'"
			style="width: 100%;display: flex;justify-content: space-between;color: aliceblue;font-size: 13px;position: fixed;top: 30px;left: 0px;z-index: 9;align-items: center;">
			
			<view class="" v-if="ispcmd">
				
			</view>
			<view v-else class="btnitem" style="margin-left: 50rpx;">
				<image @click="changetopc" v-if="!gxpcmode" src="/static/images/ggxzm.png" style="width: 60rpx;" mode="widthFix"></image>
				<image @click="changecamera" v-else src="/static/images/qqhsxt.png" style="width: 60rpx;" mode="widthFix"></image>
			</view>
			
			<view style="display: flex;align-items: center;">
				<text style="font-size: 40px;font-weight: bold;"
					:style="{'color':(t%2) == 0 ? 'green' : 'aliceblue'}">·</text> <text style="margin-top: 8rpx;">直播中</text>
			</view>
			<view style="width: 120rpx;">
				
			</view>
		</view>

		<video src="" :muted="true" :autoplay="true" id="vdbgyx"
			style="width: 100%;height: 100%;position: fixed;left: 0rpx;top: 0rpx;z-index: 1;"
			object-fit="cover"></video>

		<view
			style="width: 250rpx;display: flex;flex-direction: column;align-items: center;position: fixed;right: 25rpx;top: 60rpx;z-index: 108;padding: 15rpx;height: 70vh;overflow-y: auto;z-index: 2;">

			<view
				style="width: 100%;display: flex;padding: 15rpx;flex-direction: column;align-items: center;border-radius: 12rpx;background: #bec7df66;color: #dae3f7;margin-bottom: 15rpx;"
				v-for="(item,k) in lmuser">
				<view style="width: 100%;height: 300rpx;border-radius: 12rpx;z-index: 3;">
					<bgyx-video-small :uid="item.id" :name="item.name" :id="`bgyx_lmv${item.id}`" :src="item.stream"
						status="play" :video="item.video" :audio="item.audio" />
					<view
						style="width: 100%;display: flex;justify-content: center;align-items: center;margin-top: -60rpx;z-index: 109;">
						<image @click="kicklmuser(item)" src="/static/images/closelmuser.png"
							style="width: 60rpx;height: 60rpx;" mode=""></image>
					</view>
				</view>
			</view>
		</view>


		<view v-if="typemode == 'ready'" style="width: 100%;display: flex;flex-direction: column;align-items: center;">
			<view v-if="picture" @click="uploadimg"
				style="margin-top: 180rpx;width: 350rpx;height: 500rpx;border-radius: 12rpx;display: flex;align-items: center;justify-content: center;background: #ffffff22;flex-direction: column;z-index: 3;">
				<image :src="$store.state.common.systemInfo.fileurl + picture" style="width: 100%;" mode="widthFix">
				</image>
			</view>

			<view v-else @click="uploadimg"
				style="margin-top: 180rpx;width: 350rpx;height: 500rpx;border-radius: 12rpx;display: flex;align-items: center;justify-content: center;background: #ffffff22;flex-direction: column;z-index: 3;">
				<view class="">
					<u-icon name="plus-circle" color="whitesmoke" size="80"></u-icon>
				</view>
				<view style="color: whitesmoke;margin-top: 15rpx;">
					设置封面
				</view>
			</view>

			<view
				style="margin-top: 50rpx;width: 450rpx;border-radius: 12rpx;display: flex;align-items: center;justify-content: center;background: #ffffff22;flex-direction: column;z-index: 3;">
				<view style="width: 100%;padding: 5rpx 15rpx;">
					<u-input v-model="name" placeholder="直播间名称"></u-input>
				</view>
			</view>

			<view
				style="margin-top: 20rpx;width: 450rpx;border-radius: 12rpx;display: flex;align-items: center;justify-content: center;background: #ffffff22;flex-direction: column;z-index: 3;">
				<view style="width: 100%;padding: 5rpx 15rpx;">
					<u-input v-model="password" placeholder="直播间密码,无密码请留空"></u-input>
				</view>
			</view>

			<view
				style="margin-top: 160rpx;width: 350rpx;border-radius: 12rpx;display: flex;align-items: center;justify-content: center;background: #ffffff22;flex-direction: column;z-index: 3;">
				<view style="width: 100%;">
					<u-button @click="start" type="error">
						<view style="display: flex;align-items: center;">
							<image src="/static/images/dlplay.png" style="width: 40rpx;height: 40rpx;" mode=""></image>
							<view style="margin-left: 10rpx;">
								开始直播
							</view>
						</view>
					</u-button>
				</view>
			</view>

		</view>

		<view v-else style="width: 100%;z-index: 99;" class="btmvg">
			<view style="display: flex;width: 100%;align-items: center;justify-content: center;margin-bottom: 60rpx;">
				<view @click="changeaudio(false)" v-if="myvddata.audio" class="btnitem" style="">
					<image src="/static/images/mmic.png" style="width: 60rpx;" mode="widthFix"></image>
				</view>
				<view @click="changeaudio(true)" v-if="!myvddata.audio" class="btnitem" style="background: #ff5e5e66;">
					<image src="/static/images/mmic.png" style="width: 60rpx;" mode="widthFix"></image>
				</view>

				<view @click="changecamera" class="btnitem" style="margin-left: 50rpx;">
					<image src="/static/images/qqhsxt.png" style="width: 60rpx;" mode="widthFix"></image>
				</view>

				<view @click="changevideo(false)" v-if="myvddata.video" class="btnitem" style="margin-left: 50rpx;">
					<image src="/static/images/ccamera.png" style="width: 60rpx;" mode="widthFix"></image>
				</view>
				<view @click="changevideo(true)" v-if="!myvddata.video" class="btnitem"
					style="margin-left: 50rpx;background: #ff5e5e66;">
					<image src="/static/images/ccamera.png" style="width: 60rpx;" mode="widthFix"></image>
				</view>

				<view @click="exit" class="btnitem" style="margin-left: 50rpx;background: #ff141499;">
					<image src="/static/images/hhdown.png" style="width: 70rpx;" mode="widthFix"></image>
				</view>
			</view>
		</view>


		<u-modal v-for="(item,k) in applylist" v-model="item.applystatus == 'applying'" title="连麦申请" confirm-text="同意"
			cancel-text="拒绝" :show-cancel-button="true" @confirm="agree(item)" @cancel="refuse(item)">
			<view style="width: 100%;display: flex;flex-direction: column;align-items: center;padding-top: 46rpx;">
				<bgyx-user-avatar :id="item.id" size="46" />
				<view style="margin: 20rpx;">
					{{item.name}}
				</view>
			</view>
		</u-modal>



	</view>
</template>

<script>
	import moment from 'moment';
	import config from '../../config';
	import {
		mapState
	} from 'vuex';
	import {
		pub,
		sub,
		unsub
	} from '../../common/event';
	import utils from '../../utils';
	export default {
		data() {
			return {
				name: '',
				password: '',
				picture: '',
				stream: '',
				typemode: "ready",
				myvddata: '',
				tempvd: '',
				t: 0,
				sit: '',
				applylist: [],
				lmuser: [],
				vvvv: {},
				ispcmd: false,
				gxpcmode:false
			}
		},
		components: {

		},
		computed: {
			...mapState({

			})
		},
		onBackPress(options) {
			console.log(147, options)
			if (options.from && options.from == 'backbutton' && this.typemode == 'start') {
				return true
			}
			return false
		},
		onUnload() {
			unsub("socket_touser_applylm", this.applylm)
			unsub("socket_touser_closeapplylm", this.closeapplylm)
			unsub("socket_touser_closeapplylmx", this.closeapplylmx)
			unsub("socket_liveroomlmenter", this.liveroomlmenter)
			const user = this.$store.state.user.user
			unsub(`socket_lmuserchangeinfo_${user.id}`, this.lmuserchangeinfo)
			this.$u.put(`chat/chat/liveroom/leaveroom/${user.id}`)
			this.$store.commit(`common/setStatus`, 'normal')
			this.$u.put(`chat/chat/stopliveroom`)
			try {
				if (this.sit) {
					clearInterval(this.sit)
				}
				if (this.tempvd && this.tempvd.stream) {
					this.tempvd.unpublish()
				}
				if (this.myvddata && this.myvddata.stream) {
					this.myvddata.unpublish()
				}
				if (this.lmuser) {
					for (let o of this.lmuser) {
						o.close()
					}
				}
			} catch (e) {
				//TODO handle the exception
			}
		},
		onLoad() {
			sub("socket_touser_applylm", this.applylm)
			sub("socket_touser_closeapplylm", this.closeapplylm)
			sub("socket_touser_closeapplylmx", this.closeapplylmx)
			sub("socket_liveroomlmenter", this.liveroomlmenter)
			const user = this.$store.state.user.user
			sub(`socket_lmuserchangeinfo_${user.id}`, this.lmuserchangeinfo)
			this.$store.commit(`common/setStatus`, 'videocall')
			this.getstream()
			this.sit = setInterval(() => {
				this.t = this.t + 1
			}, 1000)
			const ispc = this.isPC()
			if(ispc){
				this.ispcmd = true
			}
		},
		methods: {
			isPC: function() {
				// 通过userAgent判断是否是PC设备
				const userAgent = navigator.userAgent;
				return /PC|Macintosh/i.test(userAgent);
			},
			lmuserchangeinfo: async function(e) {
				for (let o of this.lmuser) {
					if (o.id == e.user.id) {
						o.video = e.data.video
						o.audio = e.data.audio
						break
					}
				}
			},
			agree: async function(item) {
				item.applystatus = "agree"
				this.$socket.send({
					type: "touser_applyret_agree",
					data: {
						to: {
							id: item.id
						}
					}
				})
			},
			refuse: async function(item) {
				item.applystatus = "refuse"
				this.$socket.send({
					type: "touser_applyret_refuse",
					data: {
						to: {
							id: item.id
						}
					}
				})
			},
			kicklmuser: async function(item) {
				const user = this.$store.state.user.user
				this.$u.put(`chat/chat/removelmuser/${user.id}`, item)
			},
			applylm: async function(e) {
				e.applystatus = 'applying'
				this.applylist.push(e)
			},
			liveroomlmenter: async function(e) {
				this.applylist = this.applylist.filter(ex => ex.id != e.user.id)
				for (let o of this.lmuser) {
					if (o.id == e.user.id) {
						return
					}
				}
				setTimeout(() => {
					this.subStream(e.user)
				}, 200)
			},
			subStream: async function(e) {
				const user = this.$store.state.user.user
				const roomId = "liveroomlm" + user.id
				const id = e.id
				const pc = new RTCPeerConnection(null);
				pc.addTransceiver('audio', {
					direction: 'recvonly'
				});
				pc.addTransceiver('video', {
					direction: 'recvonly'
				});
				let offer = await pc.createOffer();
				let stream = new MediaStream();
				pc.ontrack = function(event) {
					console.log(event);
					stream.addTrack(event.track);
				};
				await pc.setLocalDescription(offer);
				let session = await new Promise(function(resolve, reject) {
					let data = {
						api: `${config.srsUrl}/rtc/v1/play/`,
						tid: id,
						streamurl: `webrtc://${config.ip}/${roomId}/${id}`,
						clientip: null,
						sdp: offer.sdp,
					};
					console.log('Generated offer: ', data);

					const xhr = new XMLHttpRequest();
					xhr.onload = function() {
						if (xhr.readyState !== xhr.DONE) return;
						if (xhr.status !== 200) return reject(xhr);
						const data = JSON.parse(xhr.responseText);
						console.log('Got answer: ', data);
						return data.code ? reject(xhr) : resolve(data);
					};
					xhr.open('POST', `${config.srsUrl}/rtc/v1/play/`, true);
					xhr.setRequestHeader('Content-type', 'application/json');
					xhr.send(JSON.stringify(data));
				});
				await pc.setRemoteDescription(
					new RTCSessionDescription({
						type: 'answer',
						sdp: session.sdp
					}),
				);

				function close() {
					stream.getTracks().forEach(function(track) {
						track.stop();
						stream.removeTrack(track);
					});
					pc.close();
				}

				const vdata = {
					id,
					roomId,
					pc,
					stream,
					audio: true,
					video: true,
					close,
				};

				this.lmuser.push(vdata)
			},
			closeapplylm: async function(e) {
				this.applylist = this.applylist.filter(ex => ex.id != e.id)
				this.lmuser = this.lmuser.filter(ex => ex.id != e.id)
			},
			closeapplylmx: async function(e) {
				try {
					for (let o of this.lmuser) {
						if (o.id == e.id) {
							await e.close()
							break
						}
					}
				} catch (e) {
					//TODO handle the exception
				}
				this.lmuser = this.lmuser.filter(ex => ex.id != e.id)
				this.applylist = this.applylist.filter(ex => ex.id != e.id)
			},
			changetopc: async function() {
				this.gxpcmode = true
				try {
					await this.myvddata.unpublish()
					setTimeout(()=>{
						this.publishStreamPc({
							video: true,
							audio: true,
						})
					},500)
				} catch (e) {
					//TODO handle the exception
				}
			},
			changecamera: async function() {
				this.gxpcmode = false
				let videoType = this.myvddata.videoType
				if (videoType == "face") {
					videoType = "environment"
				} else {
					videoType = "face"
				}
				try {
					await this.myvddata.unpublish()
					this.publishStream({
						videoType,
						video: this.myvddata.video,
						audio: this.myvddata.audio,
					})
				} catch (e) {
					//TODO handle the exception
				}
			},
			changeaudio: async function(e) {
				this.myvddata.muteAudio(e)
				this.myvddata.audio = e
				await this.$u.put(`chat/chat/liveroomchange`, {
					audio: e,
					video: this.myvddata.video
				})
			},
			changevideo: async function(e) {
				this.myvddata.muteVideo(e)
				this.myvddata.video = e
				await this.$u.put(`chat/chat/liveroomchange`, {
					video: e,
					audio: this.myvddata.audio
				})
			},
			exit: async function(e) {
				await this.$u.put(`chat/chat/stopliveroom`)
				try {
					if (this.myvddata) {
						await this.myvddata.unpublish()
					}
					for (let o of this.lmuser) {
						await o.close()
					}
				} catch (e) {
					//TODO handle the exception
				}
				this.$store.commit(`common/setStatus`, 'normal')
				uni.navigateBack()
			},
			publishStreamPc: async function(options) {
				const id = this.$store.state.user.user.id
				const roomId = 'liveroom'
				const pc = new RTCPeerConnection(null);
				pc.addTransceiver('audio', {
					direction: 'sendonly'
				});
				pc.addTransceiver('video', {
					direction: 'sendonly'
				});
				const stream = await navigator.mediaDevices.getDisplayMedia({
					audio: true,
					video: true
				})
				
				console.log(stream);
				stream.getTracks().forEach(function(track) {
					pc.addTrack(track);
				});
				let offer = await pc.createOffer();
				await pc.setLocalDescription(offer);

				let session = await new Promise(function(resolve, reject) {
					let data = {
						api: `${config.srsUrl}/rtc/v1/publish/`,
						tid: id,
						streamurl: `webrtc://${config.ip}/${roomId}/${id}`,
						clientip: null,
						sdp: offer.sdp,
					};
					console.log('Generated offer: ', data);

					const xhr = new XMLHttpRequest();
					xhr.onload = function() {
						if (xhr.readyState !== xhr.DONE) return;
						if (xhr.status !== 200) return reject(xhr);
						const data = JSON.parse(xhr.responseText);
						console.log('Got answer: ', data);
						if (data.code === 400) {
							resolve(false);
						}
						return data.code ? reject(xhr) : resolve(data);
					};
					xhr.open('POST', `${config.srsUrl}/rtc/v1/publish/`, true);
					xhr.setRequestHeader('Content-type', 'application/json');
					xhr.send(JSON.stringify(data));
				});

				console.log(session);
				if (session === false) {
					return false;
				}
				await pc.setRemoteDescription(
					new RTCSessionDescription({
						type: 'answer',
						sdp: session.sdp
					}),
				);

				function muteAudio(type) {
					stream.getTracks().forEach(function(track) {
						if (track.kind === 'audio') {
							track.enabled = type ? type : false;
						}
					});
				}

				function muteVideo(type) {
					stream.getTracks().forEach(function(track) {
						if (track.kind === 'video') {
							track.enabled = type ? type : false;
						}
					});
				}
				const _this = this

				async function unpublish() {
					try {
						stream.getTracks().forEach(function(track) {
							track.stop();
							stream.removeTrack(track);
						});
						// stream.close()
						pc.close();
						_this.myvddata.stream = null
					} catch (e) {
						//TODO handle the exception
					}
				}

				const vdata = {
					id: id,
					roomId: roomId,
					pc,
					stream,
					audio: options.audio == false ? false : true,
					video: options.video == false ? false : true,
					videoType: options.videoType ? options.videoType : "environment",
					muteAudio,
					muteVideo,
					unpublish,
					enter: true
				};

				this.myvddata = vdata

				const content = document.getElementById(`vdbgyx`);
				const items = content.getElementsByTagName("video");
				if (items && items.length > 0) {
					items[0].srcObject = stream
				}
			},
			publishStream: async function(options) {
				const retps = await utils.checkPermission("请打开摄像头和麦克风权限")
				if (!retps) {
					uni.showToast({
						title: "请打开摄像头和麦克风权限",
						icon: "none"
					})
					return
				}

				const id = this.$store.state.user.user.id
				const roomId = 'liveroom'
				const pc = new RTCPeerConnection(null);
				pc.addTransceiver('audio', {
					direction: 'sendonly'
				});
				pc.addTransceiver('video', {
					direction: 'sendonly'
				});
				const stream = await this.getStreamLoc({
					audio: true,
					video: {
						facingMode: options.videoType ? options.videoType : "environment"
					},
				})
				this.cameraType = options.videoType ? options.videoType : "environment"
				console.log(stream);
				stream.getTracks().forEach(function(track) {
					pc.addTrack(track);
					if (track.kind === 'audio') {
						if (options.audio === false) {
							track.enabled = false;
						}
					}
					if (track.kind === 'video') {
						if (options.video === false) {
							track.enabled = false;
						}
					}
				});
				let offer = await pc.createOffer();
				await pc.setLocalDescription(offer);

				let session = await new Promise(function(resolve, reject) {
					let data = {
						api: `${config.srsUrl}/rtc/v1/publish/`,
						tid: id,
						streamurl: `webrtc://${config.ip}/${roomId}/${id}`,
						clientip: null,
						sdp: offer.sdp,
					};
					console.log('Generated offer: ', data);

					const xhr = new XMLHttpRequest();
					xhr.onload = function() {
						if (xhr.readyState !== xhr.DONE) return;
						if (xhr.status !== 200) return reject(xhr);
						const data = JSON.parse(xhr.responseText);
						console.log('Got answer: ', data);
						if (data.code === 400) {
							resolve(false);
						}
						return data.code ? reject(xhr) : resolve(data);
					};
					xhr.open('POST', `${config.srsUrl}/rtc/v1/publish/`, true);
					xhr.setRequestHeader('Content-type', 'application/json');
					xhr.send(JSON.stringify(data));
				});

				console.log(session);
				if (session === false) {
					return false;
				}
				await pc.setRemoteDescription(
					new RTCSessionDescription({
						type: 'answer',
						sdp: session.sdp
					}),
				);

				function muteAudio(type) {
					stream.getTracks().forEach(function(track) {
						if (track.kind === 'audio') {
							track.enabled = type ? type : false;
						}
					});
				}

				function muteVideo(type) {
					stream.getTracks().forEach(function(track) {
						if (track.kind === 'video') {
							track.enabled = type ? type : false;
						}
					});
				}
				const _this = this

				async function unpublish() {
					try {
						stream.getTracks().forEach(function(track) {
							track.stop();
							stream.removeTrack(track);
						});
						// stream.close()
						pc.close();
						_this.myvddata.stream = null
					} catch (e) {
						//TODO handle the exception
					}
				}

				const vdata = {
					id: id,
					roomId: roomId,
					pc,
					stream,
					audio: options.audio == false ? false : true,
					video: options.video == false ? false : true,
					videoType: options.videoType ? options.videoType : "environment",
					muteAudio,
					muteVideo,
					unpublish,
					enter: true
				};

				this.myvddata = vdata

				const content = document.getElementById(`vdbgyx`);
				const items = content.getElementsByTagName("video");
				if (items && items.length > 0) {
					items[0].srcObject = stream
				}
			},
			getStreamLoc: async function(constraints) {
				if (navigator.mediaDevices.getUserMedia) {
					console.log('最新的标准API', navigator.mediaDevices.getUserMedia);
					const rs = await navigator.mediaDevices.getUserMedia(constraints)
					return rs
				} else if (navigator.webkitGetUserMedia) {
					console.log('webkit核心浏览器');
					const rs = await navigator.webkitGetUserMedia(constraints)
					return rs
				} else if (navigator.mozGetUserMedia) {
					console.log('firfox浏览器');
					const rs = await navigator.mozGetUserMedia(constraints);
					return rs
				} else if (navigator.getUserMedia) {
					console.log('旧版API');
					const rs = await navigator.getUserMedia(constraints);
					return rs
				} else {
					const rs = await navigator.mediaDevices.getUserMedia(constraints)
					return rs
				}
			},
			getstream: async function() {
				const retps = await utils.checkPermission("请打开摄像头和麦克风权限")
				if (!retps) {
					uni.showToast({
						title: "请打开摄像头和麦克风权限",
						icon: "none"
					})
					return
				}

				const stream = await navigator.mediaDevices.getUserMedia({
					video: true,
					audio: true
				})

				const content = document.getElementById(`vdbgyx`);
				const items = content.getElementsByTagName("video");
				if (items && items.length > 0) {
					items[0].srcObject = stream
				}

				async function unpublish() {
					try {
						stream.getTracks().forEach(function(track) {
							track.stop();
							stream.removeTrack(track);
						});
						_this.tempvd.stream = null
					} catch (e) {
						//TODO handle the exception
					}
				}

				this.tempvd = {
					stream,
					unpublish
				}

			},
			uploadimg: async function(e) {
				const _this = this
				uni.chooseImage({
					count: 1,
					async success(res) {
						console.log(res)
						const path = res.tempFilePaths[0]
						const ret = await utils.uploadImage(path)
						console.log(ret)
						_this.picture = ret.data.pathname
					}
				})
			},
			start: async function() {
				if (!this.picture) {
					uni.showToast({
						title: "请选择封面图",
						icon: "none"
					})
					return
				}

				const user = this.$store.state.user.user
				const data = {
					picture: this.picture,
					name: this.name ? this.name : (user.name + "的直播间"),
					uid: user.id,
					time: moment().valueOf(),
					password: this.password
				}

				const ret = await this.$u.post(`chat/chat/startliveroom`, data)

				this.typemode = 'start'

				this.publishStream({
					video: true,
					audio: true,
					videoType: 'face'
				})


			}
		}
	}
</script>


<style scoped>
	page {
		background: white;
	}

	.content {
		display: flex;
		flex-direction: column;
		align-items: center;
		width: 100%;
		height: 100vh;

	}

	.btmvg {
		width: 100%;
		display: flex;
		height: 40%;
		background: linear-gradient(to bottom, #33333300, #111111);
		position: fixed;
		left: 0rpx;
		bottom: 0rpx;
		color: white;
		align-items: flex-end;
	}

	.topvg {
		width: 100%;
		display: flex;
		height: 40%;
		background: linear-gradient(to bottom, #111111, #33333300);
		position: fixed;
		left: 0rpx;
		top: 0rpx;
		color: white;
		align-items: flex-start;
		z-index: 99;
	}

	.btnitem {
		width: 120rpx;
		height: 120rpx;
		display: flex;
		align-items: center;
		justify-content: center;
		border-radius: 160rpx;
		background: #cfcfcf55;
	}
</style>